/* eslint-disable prefer-promise-reject-errors */
import Taro from '@tarojs/taro'
import api from '@API'
import i18n from '@I18N'
import { getPlatform, isWxBrowser, getClientType } from '@UTILS/common'
import { requestSubscribeAndSave } from '@UTILS/subscribeMessage'
import {
  SUBSCRIBES_EVENT, PAY_STATUS, PAY_METHOD, WE_CHAT_PAY_STATUS, TRADE_STATE, PAYMENT_STATUS
} from '@CONSTANTS/common'
import { getJsCode } from '@UTILS/wx'
import { PaymentITF } from '@INTERFACES/Order'
import { isMobileBrowser } from './common'

const H5_PAY_DIALOG_KEY = 'H5_PAY_DIALOG'

interface PayH5DialogITF {
  orderId?: string;
  callBack: (params: any) => void;
  extraKey: string
}

interface OpenWeChatH5PayITF {
  payResult: Record<string, string>;
  extraKey: string;
  extraData: unknown;
}

const { isWX } = getPlatform()
const getMethod = () => {
  if (isWX) return PAY_METHOD.WMP_PAY
  if (isWxBrowser()) return PAY_METHOD.WECHAT_JSAPI
  return PAY_METHOD.WECHAT_H5
}
export const openWeChatH5Pay = ({ payResult, extraKey, extraData }: OpenWeChatH5PayITF): void => {
  if (!isMobileBrowser()) return
  Taro.setStorageSync(H5_PAY_DIALOG_KEY, payResult)
  if (extraKey && extraData) Taro.setStorageSync(extraKey, extraData)
  const { MwebUrl } = payResult
  window.location.href = MwebUrl
}
export const payH5Dialog = ({ orderId, callBack, extraKey }: PayH5DialogITF): void => {
  if (!isMobileBrowser()) return
  const payResult = Taro.getStorageSync(H5_PAY_DIALOG_KEY)
  if (!payResult) return
  const extraData = extraKey ? Taro.getStorageSync(extraKey) : null
  if (extraKey && !extraData) return
  const { PaymentId, Time = 0, OrderId } = payResult
  if (orderId && orderId !== OrderId) return
  if (new Date().getTime() - Time > 5 * 60 * 1000) return
  Taro.showModal({
    title: '支付确认',
    content: '请在微信内完成支付，如果您已经支付，请点击“已支付”按钮',
    confirmText: '已支付',
    confirmColor: '#47C690',
    success: res => {
      Taro.removeStorage({ key: H5_PAY_DIALOG_KEY })
      extraKey && Taro.removeStorage({ key: extraKey })
      weChatOrderQuery(res.confirm, callBack, PaymentId, extraData, payResult)
    }
  })
}
const weChatOrderQuery = async (isConfirm: boolean, callBack: (data: any) => void, pId: string, extraData: any, payResult: any) => {
  try {
    const { TradeState } = await api.weChatOrderQuery({ pId })
    if (TradeState !== TRADE_STATE.SUCCESS) {
      await Taro.showToast({ icon: 'none', title: '订单未支付' })
    }
    callBack?.({
      isSuccess: TradeState === TRADE_STATE.SUCCESS, isConfirm, extraData, payResult
    })
  } catch (error) {
    callBack?.({
      isSuccess: false, isConfirm, extraData, payResult
    })
    Taro.showToast({ icon: 'none', title: error.message || error })
  }
}

const getWxOpenId = async () => {
  let openId = await Taro.getStorageSync('wx_openid')
  if (isWX && !openId) {
    const code = await getJsCode(true)
    try {
      const { OpenId } = await api.getWeChatOpenId({ code, clientType: getClientType() })
      Taro.setStorage({
        key: 'wx_openid',
        data: OpenId
      })
      openId = OpenId
    } catch (err) {
      Taro.showToast({ title: err.message || err, icon: 'none' })
    }
  }
  return openId
}
export const pay = async (money: number, orderId: string | undefined, extraData = {}, disable = false): Promise<any> => {
  if (money <= 0) return Promise.resolve()
  try {
    const openId = await getWxOpenId()
    if ((isWX || isWxBrowser()) && !openId) {
      Taro.showModal({
        title: isWxBrowser() ? '授权过期，请刷新获取微信授权' : 'OpenId 为空',
        showCancel: false
      })
      return Promise.reject(new Error('OpenId is empty'))
    }
    const result: PaymentITF = await api.initiatePayment({
      Money: money,
      Method: getMethod(),
      ReferenceValue: orderId,
      OpenId: openId
    })
    const {
      return_code, retmsg, return_msg, UseWeChatSandBox
    } = result
    const rmsg = retmsg || return_msg
    const returnCode = Array.isArray(return_code) ? return_code[0] : return_code
    const returnMsg = Array.isArray(rmsg) ? rmsg[0] : rmsg
    if (returnCode) {
      Taro.showToast({ title: returnMsg, icon: 'none' })
      return Promise.reject(returnMsg)
    }
    if (UseWeChatSandBox) return Promise.resolve()
    if (!isWX && !isWxBrowser()) {
      return {
        MwebUrl: result.MwebUrl,
        PaymentId: result.PaymentId,
        OrderId: orderId,
        Time: new Date().getTime(),
        isMobileBrowser: true
      }
    }
    if (isWxBrowser()) return weChatH5(result)
    return requestPayment(result, extraData, disable)
  } catch (err) {
    await Taro.showToast({ title: err.message || err, icon: 'none' })
    return Promise.reject(err)
  }
}

const requestPayment = async (result: PaymentITF, extraData: any, disable: boolean) => new Promise((resolve, reject) => {
  Taro.requestPayment({
    timeStamp: result.timeStamp,
    nonceStr: result.nonceStr,
    package: result.package,
    signType: result.signType,
    paySign: result.paySign,
    success: async res => {
      if (res.errMsg === PAY_STATUS.SUCCESS) {
        !disable && await requestSubscribeAndSave(SUBSCRIBES_EVENT.CONSULTATION_SUBSCRIBES, extraData)
        return resolve(undefined)
      }
      await Taro.showToast({ title: '支付失败', icon: 'none' })
      return reject({ paymentStatus: PAYMENT_STATUS.CANCEL, message: i18n.order.payCancel() })
    },
    fail: async () => {
      await Taro.showToast({ title: '已取消支付', icon: 'none' })
      return reject({ paymentStatus: PAYMENT_STATUS.CANCEL, message: i18n.order.payCancel() })
    }
  })
})
const weChatH5 = async (result: PaymentITF) => new Promise((resolve, reject) => {
  WeixinJSBridge.invoke(
    'getBrandWCPayRequest', {
      appId: result.appId,
      timeStamp: result.timeStamp,
      nonceStr: result.nonceStr,
      package: result.package,
      signType: result.signType,
      paySign: result.paySign
    },
    async res => {
      const { err_msg } = res
      if (err_msg === WE_CHAT_PAY_STATUS.SUCCESS) {
        return resolve(undefined)
      }
      await Taro.showToast({ title: '已取消支付', icon: 'none' })
      return reject({ paymentStatus: PAYMENT_STATUS.CANCEL, message: i18n.order.payCancel() })
    }
  )
})
